package com.example.saas.interceptor;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.saas.context.DataSourceContext;
import com.example.saas.context.TenantContext;
//import com.example.saas.datasource.DynamicDataSource;
import com.example.saas.domain.DataSource;
import com.example.saas.domain.Tenant;
import com.example.saas.service.DataSourceServiceImpl;
import com.example.saas.service.TenantServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 租户拦截器
 */
@Slf4j
@Component
public class TenantInterceptor implements HandlerInterceptor {

    @Resource
    private TenantServiceImpl tenantService;
    @Resource
    private DataSourceServiceImpl dataSourceService;
//    @Resource
//    private DynamicDataSource dynamicDataSource;
    @Resource
    private javax.sql.DataSource dataSource;
    @Resource
    private DefaultDataSourceCreator dataSourceCreator;

    /**
     * 写法一：租户拦截-基于Mybatis-plus的DynamicDataSourceProvider
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String tenantId = request.getHeader("tenantId");
        if (StrUtil.isNotBlank(tenantId)) {
            TenantContext.setTenantId(tenantId);
            log.info("当前加载租户:【{}】", tenantId);
            // 查询缓存/数据库中租户对应的数据源信息
            Tenant tenant = tenantService.getById(tenantId);
            // 判断租户状态等等...
            if (ObjUtil.isNull(tenant) || (ObjUtil.isNotNull(tenant.getEndTime()) && LocalDateTime.now().isAfter(tenant.getEndTime())) || "-1".equals(tenant.getStatus())) {
                throw new RuntimeException("当前租户状态异常,暂无法使用");
            }
//            // 判断当前租户是否已配置数据源
//            if (ObjUtil.isNull(tenant.getDatasourceId())) {
//                throw new RuntimeException("当前租户未配置数据源！");
//            }
            DataSource dataSourceInfo = dataSourceService.getById(tenant.getDatasourceId());
            String key;
            if(ObjUtil.isNotNull(dataSourceInfo)){
                key = dataSourceInfo.getKey();
                // 判断当前数据源是否包含当前租户对应的数据源,如果没有则添加新数据源
                DynamicRoutingDataSource dataSources = (DynamicRoutingDataSource) dataSource;
                if(!dataSources.getDataSources().containsKey(key)){
                    DataSourceProperty dataSourceProperty = new DataSourceProperty();
                    dataSourceProperty.setDriverClassName(dataSourceInfo.getDriverClassName());
                    dataSourceProperty.setUrl(dataSourceInfo.getUrl());
                    dataSourceProperty.setUsername(dataSourceInfo.getUsername());
                    dataSourceProperty.setPassword(dataSourceInfo.getPassword());
                    dataSourceCreator.createDataSource(dataSourceProperty);
                }
            }else{
                key = "master";
                log.info("当前租户无数据源,已切换至默认数据源:{}", key);
            }
            DynamicDataSourceContextHolder.push(key);
            log.info("当前加载租户【{}】对应的数据源【{}】", tenantId, key);
        } else {
            throw new RuntimeException("错误：缺少租户信息");
        }
        return true;
    }


//    /**
//     * 写法二：租户拦截-原生AbstractRoutingDataSource
//     */
//    @Override
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//        String tenantId = request.getHeader("tenantId");
//        if (StrUtil.isNotBlank(tenantId)) {
//            TenantContext.setTenantId(tenantId);
//            log.info("当前加载租户:【{}】", tenantId);
//            // 查询缓存/数据库中租户对应的数据源信息
//            Tenant tenant = tenantService.getById(tenantId);
//            // 判断租户状态等等...
//            if (ObjUtil.isNull(tenant) || (ObjUtil.isNotNull(tenant.getEndTime()) && LocalDateTime.now().isAfter(tenant.getEndTime())) || "-1".equals(tenant.getStatus())) {
//                throw new RuntimeException("当前租户状态异常,暂无法使用");
//            }
//            // 判断当前租户是否已配置数据源
//            if (ObjUtil.isNull(tenant.getDatasourceId())) {
//                throw new RuntimeException("当前租户未配置数据源！");
//            }
//            DataSource dataSourceInfo = dataSourceService.getById(tenant.getDatasourceId());
//            String key = dataSourceInfo.getKey();
//
//            // 判断当前数据源是否包含当前租户对应的数据源,如果没有则添加新数据源
//            boolean hasKey = dynamicDataSource.isExistDataSource(key);
//            if(!hasKey){
//                Map<String, Object> dataSourceProperties = new HashMap<>();
//                dataSourceProperties.put("driverClassName", dataSourceInfo.getDriverClassName());
//                dataSourceProperties.put("url", dataSourceInfo.getUrl());
//                dataSourceProperties.put("username", dataSourceInfo.getUsername());
//                dataSourceProperties.put("password", dataSourceInfo.getPassword());
//                dynamicDataSource.addDataSource(key,dataSourceProperties);
//            }
//            DataSourceContext.setDataSourceKey(key);
//            log.info("当前加载租户【{}】对应的数据源【{}】", tenantId, key);
//        } else {
//            throw new RuntimeException("错误：缺少租户信息");
//        }
//        return true;
//    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        TenantContext.clear();
        DynamicDataSourceContextHolder.poll();
//        DataSourceContext.clearDataSourceKey();
    }
}
